#include"UdpNet.h"
#include"packDef.h"
#include<process.h>
#include"UdpMediator.h"
UdpNet::UdpNet(INetMediator* pMediator):m_sock(INVALID_SOCKET),m_hThreadHandle(NULL ),m_isStop(false)
{
	m_pMediator=pMediator;
}
UdpNet::~UdpNet()
{
	UnInitNet();
}
//初始化网络
bool UdpNet::InitNet()
{
	//1.选项目---创建库
	WORD wVersionRequested={0};
	WSADATA wsaData={0};
    int err=-1;

/* Use the MAKEWORD(lowbyte, highbyte) macro declared in Windef.h */
    wVersionRequested = MAKEWORD(2, 2);

    err = WSAStartup(wVersionRequested, &wsaData);	//WSA windows socket api
    if (err != 0) {
        /* Tell the user that we could not find a usable */
        /* Winsock DLL.                                  */
        printf("WSAStartup failed with error: %d\n", err);
        return false;
    }

/* Confirm that the WinSock DLL supports 2.2.*/
/* Note that if the DLL supports versions greater    */
/* than 2.2 in addition to 2.2, it will still return */
/* 2.2 in wVersion since that is the version we      */
/* requested.                                        */

    if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2) {
        /* Tell the user that we could not find a usable */
        /* WinSock DLL.                                  */
        printf("Could not find a usable version of Winsock.dll\n");
        WSACleanup();
        return false;
    }
    else
        printf("The Winsock 2.2 dll was found okay\n");
        
    
	//2.创建套接字
	m_sock= socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP);
		if(INVALID_SOCKET ==m_sock)
		{
			printf("socket error: %d\n",WSAGetLastError());
			WSACleanup();
			return false;
		}
		else
		{
			printf("socket succeded\n");
		}
	//申请有限广播权限
	BOOL bval = TRUE;
	setsockopt(m_sock,SOL_SOCKET,SO_BROADCAST,(char*)&bval,sizeof(bval));

	//3.选地址---绑定ip地址
		sockaddr_in server;
		server.sin_family=AF_INET;
		server.sin_port=htons(_DEF_UDP_PORT);//将整型变量从主机字节序转换成网络字节序
		server.sin_addr.S_un.S_addr=INADDR_ANY;//绑定任意网卡

	err=bind(m_sock,(sockaddr*)&server,sizeof(server));
	if(SOCKET_ERROR==err)
	{
		printf("socket error: %d\n",WSAGetLastError());
		closesocket(m_sock);
		WSACleanup();
		return false;
	}
	else
		{
			printf("bind succeded\n");
		}

	//4、接收数据——创建线程
	m_hThreadHandle = (HANDLE)_beginthreadex(NULL,0,&RecvThread ,this, 0,NULL);
	return true;
}

unsigned int __stdcall UdpNet::RecvThread( void * lpvoid )
{
	UdpNet* pThis = (UdpNet*)lpvoid;
	pThis->RecvData();
	return 0;
}



	//关闭网络
void UdpNet::UnInitNet()
 {
	 //退出线程
	 //退出标志位设置成true。尝试正常退出线程
	 m_isStop=true;
	 //等100ms，没有退出就强制杀死线程
	 if(m_hThreadHandle)
	 {
		if(WAIT_TIMEOUT==WaitForSingleObject(m_hThreadHandle,100))
		{
			TerminateThread(m_hThreadHandle,-1);
		}
		//关闭句柄
		CloseHandle(m_hThreadHandle);
		m_hThreadHandle=NULL;
	 }
	 //关闭套接字
	 if(m_sock && m_sock!=INVALID_SOCKET)
	 {
		 closesocket(m_sock);
	 }
	 //卸载库
	 WSACleanup();
 }

	//发送数据
bool UdpNet::SendData(long ISendIp,char* buf,int nLen)
{
	//设置服务器的地址信息
	sockaddr_in serverAddr;
	serverAddr.sin_family=AF_INET;
	serverAddr.sin_port=htons(_DEF_UDP_PORT);
	serverAddr.sin_addr.S_un.S_addr=ISendIp;

	if(SOCKET_ERROR ==sendto(m_sock,buf,nLen,0,(SOCKADDR*)&serverAddr,sizeof(serverAddr)))
	{
		return false ;
	}

	return true;
}
 


//接收数据
void UdpNet::RecvData()
{
	char recvBuf[_DEF_BUFFER_SIZE]="";
	sockaddr_in addrClient;
	int addrClientSize = sizeof(addrClient);
	int nRecvNum=0;
	while(!m_isStop)
	{
		
		nRecvNum=recvfrom(m_sock,recvBuf,sizeof(recvBuf),0,(sockaddr*)&addrClient,&addrClientSize);
		if(nRecvNum>0)
		{
			char * packBuf= new char[nRecvNum];
			memcpy(packBuf,recvBuf,nRecvNum);
			//通过中介者类，把数据发给kernel 类进行处理
			if(m_pMediator)
			{
				m_pMediator->DealData(addrClient.sin_addr.S_un.S_addr,recvBuf,nRecvNum);
				//回收packBuf空间，由使用数据的对象决定
			}

		}

	}

}
